#include <stdint.h>

typedef struct{
    volatile uint32_t d0,d1,d2,d3,d4,d5,d6,d7;
    volatile uint32_t a0,a1,a2,a3,a4,a5,a6,a7;

    //调用外部时的
    uint32_t bd0,bd1,bd2,bd3,bd4,bd5,bd6,bd7;
    uint32_t ba0,ba1,ba2,ba3,ba4,ba5,ba6,ba7;

}CPU_REG;

typedef uint32_t *uint32p_t;

/*
ITEM
    一号战车出场数据2d6e80，有前置条件，所以初始是2d6e5e (判断是否损耗，然后调用到2d6e80)
*/

typedef struct{
#if defined(MSLUG1)
#define ITEM_INIT 0x124
#define ITEM_MAX (0x144)
#define ITEM_INC (1)
#define ITEM_DEC (-1)
    uint8_t type;   //0x0
    uint8_t size;   //其实是相对位置
    uint16_t a1;
    uint16_t idx;
    uint16_t X;
    uint16_t Y;
    uint16_t a2;    //需要设置0x0300 否则战车攻击方向无法四周

#elif defined(MSLUG2)
#define ITEM_INIT 0x3B4
//#define ITEM_MAX (0x6a0-4)
#define ITEM_MAX (0x560-4)
    uint8_t     type;   //0x7
    uint8_t     size;   //14
    uint8_t     a1;     //0
    uint8_t     a2;     //0xb
    uint16_t    idx;    //索引
    uint16_t    X;      //x轴 ,+6
    uint16_t    Y;      //y轴 ,+8
#elif defined(MSLUGX) || 0
#define ITEM_INIT 0x2ec
#define ITEM_MAX 0x31C
    uint8_t     type;
    uint8_t     size; //默认0xA
    uint8_t     a1;   //默认9
    uint8_t     a2;     //默认0x80 ，出场居中
    //mslugx版本偏移8
    uint16_t    idx;    //2EC(mslugx)为一号战车
    uint16_t    X;      //x轴
    uint16_t    Y;      //y轴
#elif defined(MSLUG5) || defined(MSLUG3) || defined(MSLUG4)
#define ITEM_INIT 0x0
//MSLUG5 和 MSLUG3是相同的
#if defined(MSLUG5)
#define ITEM_MAX (0x3a0-4)
#elif defined(MSLUG4)
#define ITEM_MAX 0x620
#elif defined(MSLUG3)
#define ITEM_MAX 0x73C
#endif
    uint8_t     type; //应该是类型,8是生成道具
    uint8_t     a1;     //18?
    uint8_t     size; //应该是大小
    uint8_t     a2;     //0?
    uint16_t    X;      //4
    uint16_t    Y;      //6
    uint16_t    idx;    //20(mslug5)为一号战车
#else
#define ITEM_INIT 0x0
#define ITEM_MAX (0x3a0-4)
    uint8_t     type;
    uint8_t     size; //默认0xA
    uint8_t     a1;   //默认9
    uint8_t     a2;     //默认0x80 ，出场居中
    //mslugx版本偏移8
    uint16_t    idx;    //2EC(mslugx)为一号战车
    uint16_t    X;      //x轴
    uint16_t    Y;      //y轴
#endif
}ITEM;

typedef struct{
    CPU_REG save_reg;
    uint8_t skip[8];
    uint8_t key_status;
    uint8_t fire_idx;
    uint16_t    hackItem;
    ITEM    item;
}HACK_DATA;

#if defined(MSLUGX)||defined(MSLUG5)||defined(MSLUG3)||defined(MSLUG4)||1
//#define save_address (void*)(0x110090);
const void* save_address_ptr;
#define save_address save_address_ptr
#else
#define save_address (void*)(0x110090);
#endif
#define mslug5_offset -0x3356
#define mslugx_offset 0x435c

// int p(int (*c)(),CPU_REG *r){
//     if(r){
//         c();
//     }
// }

typedef struct{
    uint32_t    address;
    uint8_t     value;
}firearm_data;

typedef struct{
    #if defined(MSLUG1)
    #define P1_address 0x100440
    uint8_t _0[0x22];
    uint16_t X;
    uint16_t Y;
    #elif defined(MSLUGX)
    #define P1_address 0x1014c4
    uint8_t _0[0x28];
    uint16_t X;
    uint16_t _2A;
    uint16_t Y;
    #elif defined(MSLUG5)
        #if defined(MSLUG5)
        #define P1_address 0x100cb8
        #endif
    uint8_t _0[0x2e];
    uint16_t X;
    uint16_t _30;
    uint16_t Y;
    #elif defined(MSLUG3) || defined(MSLUG4) || defined(MSLUG2)
        #if defined(MSLUG4)
        #define P1_address 0x100cbc
        #elif defined(MSLUG2)
        #define P1_address (0x10148c+8)
        #else
        #define P1_address 0x1004fc
        #endif
    uint8_t _0[0x28];
    uint16_t X;
    uint16_t _30;
    uint16_t Y;
    #else
    #define P1_address 0x1014c4
    uint8_t _0[0x2e];
    uint16_t X;
    uint16_t _30;
    uint16_t Y;
    #endif
}Item_data;


static void setITEM(ITEM*item,uint16_t idx){
    //每个版本都不同
    Item_data *P1 = (Item_data *)P1_address;
    #if defined(MSLUG1)
    #if 0
        //测试效果
        item->type = 0;
        //item->size = 3<<3;
        if(!item->size)
            item->size = 0x40;
        //item->a1 = 0x95c;
        if(!item->X)
            item->X = P1->X;
        if(!item->Y)
            item->Y = P1->Y+12;
    #else
        item->type = 0;
        //item->size = 3<<3;
            item->size = 0x4|0xC0;  //相对屏幕位置，和P1->X P1->Y是一样的
            item->Y = P1->Y+12;

            //0xC0 需要 -0x200 再取反
            item->Y -= 0x200;
            item->Y = ~item->Y;

            //item->a1 = 0x95c;
            item->X = P1->X;

            item->a2 = 0x300;  //0x300版本，可以斜着射击
    #endif
    #elif defined(MSLUG2)
        item->type = 7;
        item->size = 0xa;
        item->a1 = 0;
        item->a1 = 0xb;
        item->X = P1->X;
        item->Y = P1->Y+12;
    #elif defined(MSLUGX)
        item->a1 = 9;

        item->size = 0xa;
        item->type = 7;


        #if 0
        h->item.a2 = 0x80;
        h->item.X = 80;
        h->item.Y = 400;
        #else
        item->a2 = 0;
        item->X = P1->X;
        item->Y = P1->Y+12;
        #endif
    #elif defined(MSLUG5) || defined(MSLUG3) || defined(MSLUG4)
        item->type = 8;
        item->size = 0xc;
        item->a1 = 0x18;
        item->a2 = 0;
        item->X = P1->X;
        item->Y = P1->Y+12;;
    #endif
    item->idx = idx;
}

static const firearm_data a1[] = {
    {0x10D454,0},
    {0x100D58,0},
    {0,0},
};

static const firearm_data a2[] = {
    {0x10D454,2},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a3[] = {
    {0x10D454,3},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a4[] = {
    {0x10D454,4},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a5[] = {
    {0x10D454,4},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a6[] = {
    {0x10D454,5},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a7[] = {
    {0x10D454,6},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a8[] = {
    {0x10D454,7},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a9[] = {
    {0x10D454,8},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a10[] = {
    {0x10D454,9},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a11[] = {
    {0x10D454,0xa},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a12[] = {
    {0x10D454,0xb},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a13[] = {
    {0x10D454,0xc},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a14[] = {
    {0x10D454,0xd},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a15[] = {
    {0x10D454,0xe},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a16[] = {
    {0x10D454,0xf},
    {0x100D58,1},
    {0,0},
};

static const firearm_data a17[] = {
    {0x10D454,0x12},
    {0x100D58,2},
    {0,0},
};

const firearm_data* const hack_f[] = {
    a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,
};

typedef void (*CreateITEM)(ITEM*item);

enum key{
    key_up    = 1<<0,
    key_down  = 1<<1,
    key_left  = 1<<2,
    key_right = 1<<3,
    key_a     = 1<<4,
    key_b     = 1<<5,
    key_c     = 1<<6,
    key_d     = 1<<7,
};

static const int16_t errITEM[] = {
#if defined(MSLUG4)
    0x10,0x2c,
#endif
    -1
};

#ifndef ITEM_INC
#define ITEM_INC 4
#define ITEM_DEC -4
#endif

void hack(){
    volatile CPU_REG *reg = (CPU_REG*)save_address;
    volatile uint8_t *d0p = &reg->d0;
    volatile uint8_t *d1p = &reg->d1;
    volatile uint8_t *A5 = (uint8_t*)reg->a5;
    HACK_DATA *h = (HACK_DATA *)save_address;
    //Item_data *P1 = (Item_data *)0x1014c4;
    //获得键盘状态
    //
    #ifdef MSLUGX
    uint8_t d1 = A5[mslugx_offset+1];
    uint8_t d0 = A5[mslugx_offset];
    #elif defined(MSLUG3)
    uint8_t d1 = A5[-0x7f6c+1];
    uint8_t d0 = A5[-0x7f6c];
    #elif defined(MSLUG5)
    uint8_t d1 = A5[mslug5_offset+1];
    uint8_t d0 = A5[mslug5_offset];
    #elif defined(MSLUG4)
    uint8_t d1 = A5[-0x1bba+1];
    uint8_t d0 = A5[-0x1bba+0];
    #elif defined(MSLUG2)
    //uint8_t d1 = A5[-0x1bba+1];
    uint8_t d0 = A5[-0x1ae2];
    uint8_t d1 = 0;
    #elif defined(MSLUG1)
    uint8_t d0 = ((uint8_t*)(0x10e200))[1];
    uint8_t d1 = ((uint8_t*)(0x10e200))[2];
    #else
    uint8_t d1 = 0;
    uint8_t d0 = 0;
    #endif
    //写回到备份
    // *(volatile uint8_t*)(&reg->d0) = d0;
    // *(volatile uint8_t*)(&reg->d1) = d1;
    // reg->d0 = (reg->d0&0xffffff00)|d0;
    // reg->d1 = (reg->d1&0xffffff00)|d1;
    #ifdef MSLUGX
    // if(d0!=0){
    //     A5[mslugx_offset] = 0x10;
    //     A5[mslugx_offset+1] = 0x10;
    // }
    #endif

    if(h->key_status&key_d){
        h->key_status = d0;
        return;
    }
    h->key_status = d0;
    #if defined(MSLUG5) || defined(MSLUG4) || defined(MSLUG3)
    if(h->hackItem>ITEM_MAX){
    #else
    if(h->hackItem==0){
    #endif
        h->hackItem = ITEM_INIT;
    }
    if(d0&key_d){
        //d键
        #if 0
        h->item.a1 = 9;

        h->item.size = 0xa;
        h->item.type = 7;


        #if 0
        h->item.a2 = 0x80;
        h->item.X = 80;
        h->item.Y = 400;
        #else
        h->item.a2 = 0;
        h->item.X = P1->X;
        h->item.Y = P1->Y+8;
        #endif
        #endif

        if(d0&key_b){
            //初始化
            h->hackItem = //0x2ec;
                ITEM_INIT;
        }

        if(d0&key_down){
            if(h->hackItem<ITEM_MAX){
                h->hackItem += ITEM_INC;
            }
            else{
                h->hackItem = 0;
            }
            #if defined(MSLUG5)
            //特殊场景不能乘坐这些载具
            while(h->hackItem>=0x18&&h->hackItem<=0x1c){
                h->hackItem += ITEM_INC;
            }
            #endif
            int i = 0;
            while(errITEM[i]>0){
                if(h->hackItem==errITEM[i]){
                    //出现错误的选项
                    h->hackItem += ITEM_INC;
                    i = 0;
                }
                i++;
            }
        }
        else if(d0&key_up){
            h->hackItem -= 4;
            #if defined(MSLUG5)
            while(h->hackItem>=0x18&&h->hackItem<=0x1c){
                h->hackItem += ITEM_DEC;
            }
            #endif
            int i = 0;
            while(errITEM[i]>0){
                if(h->hackItem==errITEM[i]){
                    //出现错误的选项
                    h->hackItem += ITEM_DEC;
                    i = 0;
                }
                i++;
            }
        }

        if(h->hackItem>ITEM_MAX){
            h->hackItem = ITEM_MAX - ITEM_INC*2;
        }

        //h->item.idx = h->hackItem;    //1号战车
        //mslug5  314直接救出人质
        setITEM(&h->item,h->hackItem);

        CreateITEM c = (CreateITEM)0x1a0a6;
        /*
        其实这个为事件

        */
        createItem(&h->item);

        /*能使用*/
        //createItem(0x2D6E5A);
        //createItem(0x2D6E80);
    }
    //保存旧数据


    //
    // if(h->key_status&key_d){
    //     //key_status已经按下
    //     h->key_status = d0;
    //     return;
    // }
    // h->key_status = d0;
    // if(h->key_status&key_d){
    //     if(h->fire_idx>=sizeof(hack_f)/sizeof(hack_f[0])){
    //         h->fire_idx = 0;
    //     }
    //     if(h->key_status&key_up){
    //         h->fire_idx ++;
    //     }
    //     {
    //         int idx = h->fire_idx;
    //         int next = 0;
    //         //切换武器
    //         while(hack_f[idx][next].address){
    //             uint8_t*ptr = (uint8_t*)hack_f[idx][next].address;
    //             ptr[0] = hack_f[idx][next++].value;
    //         }
    //     }
    // }

    //返回主程序
}
